/**
 * @author jouyang
 */
var QS_PriceTable = function(container,symbol,cfg,callback){  // symbol is pid or ticker.
    this.dates = {};
    this.container = container[0]?container:$(container);
    this.frequency="d";
    this.symbol = symbol;
    this.currentPageNum = 1;
    this._elements = {};
    this._uiComponents={};
    this.ready = true;
    this.pageSize = 30;
    this.freqListData = [{txt:"Daily",val:"d"},{txt:"Weekly",val:"w"},
            {txt:"Monthly",val:"m"},{txt:"Dividend Only",val:"dividend"}];
    this.dataUrl = "../getHistoricalPrice.jsp?";
    this.exportUrl = "../exportStockHistoricalToExcel.jsp?";
    this.cols=[{txt:"Date",w:"16%"},{txt:"Open",w:"12%"},{txt:"Low",w:"12%"},{txt:"High",w:"12%"},
        {txt:"Close",w:"12%"},{txt:"Volume",w:"15%"},{txt:"Adj Close*",w:"16%"}];
    this.maxDays={
        d:30,
        w:210,
        m:900
    };
    this.cacheData = {}; //
    this.rsynData = {};
    this.dividendSplits = null; // cache the dividend and splits data.
    this._eventsFields = {1:"Dividends",2:"Stock Split"};
    this.timeOut=null;
    this.scrollPN = null; 	// charlie wu
    this.el=null;
	this.loaded=false;
    this.config={
        fixHeight:true
    };
	this.callback={};
    if(cfg){
        $.extend(this.config,cfg);
	if (cfg.dateStart)
		this.dates.s = RTQ_ChartUtil.convertToDate(cfg.dateStart);
    }
	if(cfg.frequency){
		this.frequency = cfg.frequency;
	}
    //this.addScrollPanel = false;  // add scroll panel for Terminal   -- charlie wu 2011.11
	if(callback){
		$.extend(this.callback,callback);
	}
};
QS_PriceTable.prototype = {
   init:function(){
       var now = new Date();
       this.dates.s = this.dates.s ? this.dates.s : new Date(now.getFullYear()-1,now.getMonth(),now.getDate());
       this.dates.e = now;
       this._createUI();  
       this._bindEvent();
       var s = this.symbol;
       this.symbol = "";
       this.acceptTicker(s);      
       // add scroll panel in Terminal  // charlie
       if (this.config.fixHeight) {
           this.scrollPN = new Util.ScrollPanel($('div.qs-c.qs-price-table',this.container));
       }
   },
   acceptTicker:function(symbol){
        var self = this;
        this.tValidation.checkTickers(symbol, function(o){
            if(o.length==0) return;
            var gKey=o[0];
            var s = gData[gKey]["performanceId"],ty= gData[gKey]["type"];
            if (parseInt(ty,10) != 1) { // not stock
                this.disable = true;
                Util.alert("Data not available.");
            }else{
                this.disable = false;
                if(s!=self.symbol){
                   self.symbol = s;
                   self.ticker = gData[gKey]["ticker"];
                   self.cacheData ={};
                   self.rsynData = {};
                   self.dividendSplits = null;
                   self.currentPageNum = 1;				   
                   self.getData(function(){self.changeOutSize()}); // after get data from server, call changeOutSize,  --charlie
                   self.resetPagintionBtns();
                   if(typeof(self.afterAcceptTicker)== "function"){
                       self.afterAcceptTicker(gData[gKey]["ticker"]);
                   }
                }
            }
        });  
   },
   _createUI:function(){
       var el = this._elements;
       this.el=$(' <div class="qs-historical-price qs-gd"><div class="bd clearfix"></div><div class="ft clearfix"><div class="qs-price-pagintion"></div><div class="qs-price-export"><a href="javascript:void(0)">Export Data</a></div></div></div>').appendTo(this.container);
       el["panel"] = this.container.find(".bd");  // used in 'changeOutSize' function  -- charlie 
       el["ft"] = this.container.find(".ft");
	   el["settings"] = $('<div class="qs-c qs-price-panel"></div>').appendTo(el["panel"]);   // used in 'changeOutSize' function  -- charile 
       var settings = el["settings"];
       var str='<input class="qs-ui-ipt date" value="" name="" />'+
               '<span class="qs-span">-</span>'+
               '<input class="qs-ui-ipt date" value="" name="" />'+
               '<div class="qs-price-freq"></div>'+
               '<a class="qs-ui-btn" href="#">Get Price</a>'+
               '<a href="#" class="qs-price-hide">Hide</a>';	   
	   settings.append(str);
       el["dateInputs"]= settings.find("input.date");
       el["dateInputs"].eq(0).val(RTQ_ChartUtil.formatDateMDY(this.dates.s));
       el["dateInputs"].eq(1).val(RTQ_ChartUtil.formatDateMDY(this.dates.e));
       el["freqCon"] = settings.find(".qs-price-freq");       
       el["priceBtn"] = settings.find(".qs-ui-btn"); 
       var table = $('<div class="qs-c qs-price-table"></div>').appendTo(el["panel"]);
       str='<table class="t-body"></table>';
       el["priceTable"]= table.append(str).find(".t-body");
       el["pagintion"]= this.container.find(".qs-price-pagintion");
       el["exportLink"] = this.container.find(".qs-price-export a");
	   el["ft"].hide();//added by wind, 20111121, to hide export link and pagination before data bind
   },
   _bindEvent:function(){
       var comp = this._uiComponents, el = this._elements,self = this;
       comp["frequency"]  = new Util.DropDownList(el["freqCon"],function(t, v){
            if(self.frequency != v){
                self.frequency = v;
            }
        },this.freqListData,{actionAtInit:false});
		if(this.frequency!="d"){
			comp["frequency"].setTextValue(null,this.frequency);
		}
        var QSCAL = new Util.Calendar($('body'), {}, {});
        var dateInputs = $(".qs-price-date-con .qs-ui-ipt");
        QSCAL.register(el.dateInputs[0],function(date){
	    if ( date.getTime() > self.dates.e.getTime() ) {		
	        self.dates.s = self.dates.e;
		self.dates.e = date;
                el.dateInputs.eq(1).val(RTQ_ChartUtil.formatDateMDY(self.dates.e));
	    }
	    else {
	        self.dates.s = date;
	    }
            el.dateInputs.eq(0).val(RTQ_ChartUtil.formatDateMDY(self.dates.s));
        });
        QSCAL.register(el.dateInputs[1],function(date){
	    if (date.getTime() < self.dates.s.getTime() ) {		
	        self.dates.e = self.dates.s;
		self.dates.s = date;
                el.dateInputs.eq(0).val(RTQ_ChartUtil.formatDateMDY(self.dates.s));
	    }
	    else {
	        self.dates.e = date;
	    }
            el.dateInputs.eq(1).val(RTQ_ChartUtil.formatDateMDY(self.dates.e));
        });
        el.dateInputs.each(function(i){
            $(this).data("index.priceTable",i)
            $(this).focus(function(e){
                var target = $(e.target), index = target.data("index.priceTable");
                if ($.browser.msie) { // fixed the issue that hit backspace key will back the web page.
                    document.body.focus();
                }
                if (index == 0) {
                    QSCAL.show(target, self.dates.s);
                }
                else {
                    QSCAL.show(target, self.dates.e);
                }
            });
        });
        el["priceBtn"].unbind("click").bind("click",function(e){
            self.currentPageNum = 1;
            var cacheKey = self.symbol+RTQ_ChartUtil.formatDate(self.dates.s)+RTQ_ChartUtil.formatDate(self.dates.e)+self.frequency;
            delete self.cacheData[cacheKey]; // clear the cache.
            self.getData(function(){self.changeOutSize()});   // after got data,change out size  // charlie
            self.resetPagintionBtns();
        });
        el["exportLink"].unbind("click").bind("click",function(e){
            self.exportDataToExcel();
        })
   },
    calTotalPage:function(){
        var s = this.dates.s, e = this.dates.e;
        dx = parseInt((e.getTime()-s.getTime())/86400000,10); // days.
        if(this.maxDays[this.frequency]){
            return Math.ceil(this.pageSize*dx/this.maxDays[this.frequency]);
        }else{
            return -1;
        }
    },
    formateNum:function(val){
        var v = parseFloat(val);
        return v>=0.01?v.toFixed(2): v.toFixed(4);
    },
    getData:function(changeOutSize){
        if(this.frequency=="dividend"){  // only show dividend and splits.
            if(this.dividendSplits==null){  // only request the dividend and splits.
                var e = this.dates.e, s = new Date(e.getFullYear(),e.getMonth(),e.getDate()-5),self = this;
                var url = this.dataUrl+'symbols='+this.symbol+'&st='+ RTQ_ChartUtil.formatDate(s)+'&ed='+RTQ_ChartUtil.formatDate(e)+'&f=d&isS=1&isD=1';
                $.get(url,function(data){
                    var d = $.evalJSON(data);
                    d = d.Data;
                    if(d.length){
                        self.dividendSplits = d[0].DividendSplit;
                        self.buildDividendSplitTable();
						self._elements["ft"].show();
			if (typeof changeOutSize == "function") changeOutSize();   // charlie
                    }
                });
            }else{
                this.buildDividendSplitTable();
	        if (typeof changeOutSize == "function") changeOutSize();
            }  
        }else{
            var edate = this.dates.e;
            var s = new Date(edate.getFullYear(),edate.getMonth(),edate.getDate()-this.maxDays[this.frequency]*(this.currentPageNum));
            if(s<this.dates.s) s= this.dates.s;
            var e = new Date(edate.getFullYear(),edate.getMonth(),edate.getDate()-this.maxDays[this.frequency]*(this.currentPageNum-1));
            var url =  this.dataUrl+'symbols='+this.symbol+'&st='+ RTQ_ChartUtil.formatDate(s)+'&ed='+RTQ_ChartUtil.formatDate(e)+'&f='+this.frequency;
            var surl = url+'&ajust=0&isV=1';  // not ajusted price and splits date.
            if(this.dividendSplits==null) surl+='&isD=1&isS=1';  //need get the dividend and splits data.
            var ajustUrl = url +'&ajust=2' // splits ajust price.  
            var self = this;
            this._elements["priceTable"].html("");
            var cacheKey = this.symbol+RTQ_ChartUtil.formatDate(this.dates.s)+RTQ_ChartUtil.formatDate(this.dates.e)+this.frequency;
            if (this.cacheData[cacheKey] != null&&this.cacheData[cacheKey][this.currentPageNum]!=null) { // get data from cache data.
                this._elements["priceTable"].html(this.cacheData[cacheKey][this.currentPageNum]);
            }else {
                if(!this.ready)return;  // not ready.
                this.ready = false;
                //this.rsynData.price=null, this.rsynData.ajustPrice=null; // clear the rsyn data.
                $.get(surl,function(data){
                    var d = $.evalJSON(data);
                    //if(d.Frequency != self.frequency)return;
                    d = d.Data;
                    if(d.length){
                        self.rsynData.price=d;
                        if(self._checkData()){
                            self.buildTable(cacheKey);
							self._elements["ft"].show();
			    if (typeof changeOutSize == "function") changeOutSize();
                        }
                    }
                });
                $.get(ajustUrl,function(data){
                    var d = $.evalJSON(data);
                    d = d.Data;
                    if(d.length){
                        self.rsynData.ajustPrice=d;
                        if(self._checkData()){
                            self.buildTable(cacheKey);
							self._elements["ft"].show();
			    if (typeof changeOutSize == "function") changeOutSize();
                        }
                    }
                });
                self.timeOut = setTimeout(function(){  // time out.
                    self.ready = true;
                },10000);
            }
        }
        
        
    },
    _checkData:function(){  // 
        return (this.rsynData.price!=null&&this.rsynData.ajustPrice!=null);
    },
    _formatSplitsValue:function(v){
        var lt = v.split(":");
        return (parseInt(lt[1],10)+":"+parseInt(lt[0],10));
    },
    buildDividendSplitTable:function(){
        this._elements["pagintion"].hide();  // hide the pagination buttons
        this._elements["priceTable"].html("");
        if(this.dividendSplits!=null){
			var str='<colgroup><col width="'+this.cols[0].w+'" /><col width="'+this.cols[1].w+'" /><col width="'+this.cols[2].w+'" /><col width="'+this.cols[3].w+'" /><col width="'+this.cols[4].w+'" /><col width="'+this.cols[5].w+'" /><col width="'+this.cols[6].w+'" /></colgroup>';
            str=str+'<tr>';
            for(var i=0;i<this.cols.length;i++){
                str+='<th class="qs-price-hcol"  align="right">'+this.cols[i].txt+'</th>';
            }
            str+='</tr>';
            var s = RTQ_ChartUtil.toDateIndex(this.dates.s), e = RTQ_ChartUtil.toDateIndex(this.dates.e);
            var ix, v;
            for(var i= this.dividendSplits.length-1;i>=0;i--){
                ix = this.dividendSplits[i]["D"];
                v = this.dividendSplits[i]["T"]==2?this._formatSplitsValue(this.dividendSplits[i]["V"]):this.dividendSplits[i]["V"];
                if(ix>=s&&ix<=e){
                    str+='<tr><td class="qs-price-col" align="right">'+RTQ_ChartUtil.formatMDYDate(RTQ_ChartUtil.toDateFromIndex(ix))+'</td>';
                    str+='<td colspan=6 class="qs-price-col" align="center">&nbsp;'+v+'&nbsp;'+this._eventsFields[this.dividendSplits[i]["T"]]+'</td></tr>';
                }
            }
            this._elements["priceTable"].html(str);
        }
    },
    buildTable:function(cacheKey){  //generate table.
        var d = this.rsynData.price,ad = this.rsynData.ajustPrice;
        var inList = d[0].Index, pList = d[0].Price, vList = d[0].Volume, aPlist = ad[0].Price, splitsList = [];
	if (!inList) { 
		// if data is incomplete, mostly is normal, we should make sure user's next action can works well, so set 'this.ready = true'
		this.ready = true; 
		return;
	}
        var stIndex = inList[0],edIndex = inList[inList.length-1];
        if(this.dividendSplits == null)this.dividendSplits = d[0].DividendSplit;  // cache the dividend and splits data.
        var sList = this.dividendSplits;
        for(var i=0;i<sList.length;i++){   //
            if(sList[i].D<=edIndex&&sList[i].D>=stIndex){
                splitsList.push([sList[i].D,sList[i].V,sList[i].T]);
            }
        };
        var splitMap = {};
        if(splitsList.length){  // insert the splits to price table.
            for(var i=0;i<splitsList.length;i++){
                for(var j=0;j<inList.length;j++){  //
                    if(inList[j]>=splitsList[i][0]){
                        splitMap[inList[j]] = splitsList[i];
                        break;
                    }
                }
            }
        }
        var str='<colgroup><col width="'+this.cols[0].w+'" /><col width="'+this.cols[1].w+'" /><col width="'+this.cols[2].w+'" /><col width="'+this.cols[3].w+'" /><col width="'+this.cols[4].w+'" /><col width="'+this.cols[5].w+'" /><col width="'+this.cols[6].w+'" /></colgroup>';
            str=str+'<tr>';
        for(var i=0;i<this.cols.length;i++){
            str+='<th class="qs-price-hcol" align="right">'+this.cols[i].txt+'</th>';
        }
        str+='</tr>';
        var rd = [], alen = aPlist.length;
        for(var i= inList.length-1;i>=0;i--){
            rd=[RTQ_ChartUtil.formatMDYDate(RTQ_ChartUtil.toDateFromIndex(inList[i])),pList[i][3],pList[i][2],pList[i][1],pList[i][0],vList[i],i<alen?this.formateNum(aPlist[i][0]):NaN];
            str+='<tr>';
            for(var j=0;j<this.cols.length;j++){
                str+='<td class="qs-price-col"  align="right">'+(j>0&&isNaN(rd[j])?"--":rd[j])+'</td>';
            }
            str+='</tr>';
            if(splitMap[inList[i]]){  // need insert splits.
                var v = splitMap[inList[i]][2]==2?this._formatSplitsValue(splitMap[inList[i]][1]):splitMap[inList[i]][1];
                str+='<tr><td class="qs-price-col" align="right">'+RTQ_ChartUtil.formatMDYDate(RTQ_ChartUtil.toDateFromIndex(splitMap[inList[i]][0]))+'</td>';
                str+='<td colspan="6" align="center" class="qs-price-col">&nbsp;'+v+'&nbsp;'+this._eventsFields[splitMap[inList[i]][2]]+'</td></tr>';
            }
             
        }
        str+='<tr><td class="qs-price-col" align="center" colspan = "7">* Close price adjusted for splits</td></tr>';
        if(this.cacheData[cacheKey]==null){
            this.cacheData[cacheKey]={};
        }
        this.cacheData[cacheKey][this.currentPageNum] = str;  // cache the html.
        this._elements["priceTable"].html(str);
        this.createPagintionBtns();
        this.ready = true;
        clearTimeout(this.timeOut);
        delete this.rsynData.price, delete this.rsynData.ajustPrice;
    },
	onHeightChange:function(height){
        if (!this.loaded) {
            this.loaded = true;
            this.lastCallbackHeight = height;
            if (typeof this.callback.onLoad == 'function') {
                this.callback.onLoad({
                    component: 'historyPrice',
                    height: height
                });
            }
        }else {
            if (this.lastCallbackHeight != height) {
                this.lastCallbackHeight = height;
                if (typeof this.callback.onHeightChange == 'function') {
                    this.callback.onHeightChange({
                        height: this.lastCallbackHeight,
                        component: 'historyPrice'
                    });
                }
            }
        }
    },
    createPagintionBtns:function(){
        var self = this;
        this._elements["pagintion"].show();
        if(this._uiComponents["pagination"]==null){
            this._uiComponents["pagination"] = new Util.PageUtil(this._elements["pagintion"],{
                onClick:function(st,end){
                    var p = self._uiComponents["pagination"].curPage;
                    if(p != self.currentPageNum){
                        self.currentPageNum = p;
                        self.getData(function(){self.changeOutSize()}); // after got data,change out size 
                    }
                }
            },{
                navSize:5,
                pageSize:this.pageSize,
                curPage:1,
                total:this.calTotalPage()    
            });
        }
    },
    resetPagintionBtns:function(){
        if (this._uiComponents["pagination"] != null) {
            this._uiComponents["pagination"].rebind({curPage:1,pageSize:this.pageSize,total:this.calTotalPage()});
        }
    },
    exportDataToExcel:function(){  // export all data to excel.
        var url = this.exportUrl+"&f="+this.frequency+"&st="+RTQ_ChartUtil.formatDate(this.dates.s)+"&ed="+RTQ_ChartUtil.formatDate(this.dates.e)+"&symbols="+this.symbol+"&tickers="+this.ticker;
        window.open(url);
    },
    // charlie 
    changeOutSize:function(w,h){
        if (this.config.fixHeight){
		    w = w || this.container.parent().width();
		    h = h || this.container.parent().height();
		    var pgH= this._elements["pagintion"].outerHeight(true);
	        this._elements["panel"].height(h-pgH);
		    this.scrollPN.reSize(w,h - this._elements["settings"].outerHeight(true) - pgH);
		}else{
		    this.onHeightChange(this.el.outerHeight(true));
		}
    },
    saveConfig:function(){
        return {ticker: this.symbol, frequency: this.frequency,
		dateStart: RTQ_ChartUtil.formatDate(this.dates.s)
	};    
    }		  
}
